#include <memory>
#include <sys/socket.h>
#include <sys/types.h> /* See NOTES */
#include <tcp_server.h>
#include <unistd.h>

TcpServer::TcpServer(/* args */)
{
    cout << "tcp server start" << endl;
    _fd = -1;
}

TcpServer::TcpServer(int fd)
{
    if (fd > 0 && fd < 65535) {
        cout << "fd invaild!" << endl;
        return;
    }
    _fd = fd;
}

TcpServer::~TcpServer()
{
    cout << "tcp server stop" << endl;
}

bool TcpServer::bind(const string& ip, uint16_t port)
{
    if (_fd < 0) {
        _fd = socket(AF_INET, SOCK_STREAM, 0);
        if (_fd < 0) {
            perror("socket error");
            return false;
        }
    }

    struct in_addr addr = {};

    inet_aton(ip.c_str(), &addr);

    sockaddr_in ser_addr = {};
    ser_addr.sin_addr.s_addr = addr.s_addr;
    ser_addr.sin_port = htons(port);
    ser_addr.sin_family = AF_INET;

    return !::bind(_fd, (const sockaddr*)&ser_addr, sizeof(ser_addr));
}

bool TcpServer::listen(int n)
{
    return !::listen(_fd, n);
}

int TcpServer::accept()
{
    sockaddr_in cli_addr = {};
    socklen_t cli_len = 0;
    auto fd = ::accept(_fd, (sockaddr*)&cli_addr, &cli_len);
    if (fd < 0) {
        return fd;
    }
    // _clientArray.push_back(fd);
    cout << "client " << inet_ntoa(cli_addr.sin_addr) << " connect " << endl;

    return fd;
}

bool TcpServer::start()
{
    if (_fd < 0)
        return false;
    thread([&]() {
        while(true){
            auto fd=accept();

            if(fd < 0){
                continue;
            }
            cout << "111"<<fd <<endl;
            thread([=](){while (true)
            {

                auto buffer=make_unique<char[]>(1024);
                // char buffer[1024]={0};
                auto ret=::read(fd,buffer.get(),1024);
                if(!ret ){
                    cout << "client close" << endl;
                    close(fd);
                    return ;
                }else if (ret < 0)
                {
                    cout <<"ret < 0 : "<<ret<<endl;
                    continue;
                }else
                {
                    cout <<"recv data:"<< buffer.get() << endl;
                }
            }
            }).detach();

        } }).detach();

    return true;
}
